package com.wiscamp.ninechapters.panels.application.services;

import com.wiscamp.ninechapters.panels.application.assemblers.ApplicationAssembler;
import com.wiscamp.ninechapters.panels.application.command.CreateApplicationCommand;
import com.wiscamp.ninechapters.panels.application.command.UpdateApplicationCommand;
import com.wiscamp.ninechapters.panels.application.vo.ApplicationVO;
import com.wiscamp.ninechapters.panels.domain.repositories.ApplicationRepository;
import com.wiscamp.ninechapters.panels.domain.services.ApplicationService;
import cube.ddd.application.BaseAppService;
import cube.ddd.application.command.DeleteCommand;
import cube.ddd.application.command.DisableCommand;
import cube.ddd.application.command.EnableCommand;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.common.query.PagedObjects;
import cube.ddd.common.query.PagedQuery;
import cube.ddd.utils.AppServiceUtils;
import jakarta.validation.Valid;
import org.springframework.stereotype.Service;

import java.util.Collection;

@Service
public class ApplicationAppService extends BaseAppService {

    private final ApplicationRepository applicationRepository;

    private final ApplicationService applicationService;

    public ApplicationAppService(ApplicationRepository applicationRepository, ApplicationService applicationService) {
        this.applicationRepository = applicationRepository;
        this.applicationService = applicationService;
    }

    @HandleServiceException
    public ApplicationVO getApplication(long appId) {
        return AppServiceUtils.getById(appId, applicationService::getApplication,
                ApplicationAssembler.Instance::toApplicationVO);
    }

    @HandleServiceException
    public ApplicationVO getApplicationByCode(String appCode) {
        return AppServiceUtils.getByText(appCode, applicationRepository::getApplicationByCode,
                ApplicationAssembler.Instance::toApplicationVO);
    }

    @HandleServiceException
    public Collection<ApplicationVO> getApplicationsByName(String appName) {
        return AppServiceUtils.getListByText(appName, applicationRepository::getApplicationsByName,
                ApplicationAssembler.Instance::toApplicationVO);
    }

    @HandleServiceException
    public Collection<ApplicationVO> getApplicationsByGroup(String appGroup) {
        return AppServiceUtils.getListByText(appGroup, applicationRepository::getApplicationsByGroup,
                ApplicationAssembler.Instance::toApplicationVO);
    }

    @HandleServiceException
    public Collection<ApplicationVO> getAvailableApplications() {
        return AppServiceUtils.getList(applicationRepository::getAvailableApplications,
                ApplicationAssembler.Instance::toApplicationVO);
    }

    @HandleServiceException
    public PagedObjects<ApplicationVO> getApplicationsByQuery(PagedQuery pagedQuery) {
        var pagedObjects = applicationRepository.getApplicationsByQuery(pagedQuery);
        return AppServiceUtils.convertPagedObjects(pagedObjects, ApplicationAssembler.Instance::toApplicationVO);
    }

    @HandleServiceException
    public ApplicationVO createApplication(@Valid CreateApplicationCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), applicationService::createApplication,
                ApplicationAssembler.Instance::toApplicationVO, ApplicationAssembler.Instance::fromCreateCommand);
    }

    @HandleServiceException
    public ApplicationVO updateApplication(@Valid UpdateApplicationCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), applicationService::updateApplication,
                ApplicationAssembler.Instance::toApplicationVO, ApplicationAssembler.Instance::fromUpdateCommand);
    }

    @HandleServiceException
    public boolean deleteApplication(@Valid DeleteCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.delete(command.getId(), command.getOperatorId(), applicationService::deleteApplication);
    }

    @HandleServiceException
    public boolean enableApplication(@Valid EnableCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.enable(command.getId(), command.getOperatorId(), applicationService::enableApplication);
    }

    @HandleServiceException
    public boolean disableApplication(@Valid DisableCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.disable(command.getId(), command.getOperatorId(), applicationService::disableApplication);
    }
}
